﻿namespace Assets.Common.Unity
{
    using UnityEngine;
    using UnityEngine.Pool;

    /// <summary>
    /// 对象池组件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ComponentPool<T> : MonoBehaviour where T : Component
    {
        [SerializeField] protected T prefab;
        [SerializeField] int defaultSize = 32;
        [SerializeField] int maxSize = 500;

        ObjectPool<T> pool;

        public int ActiveCount => pool.CountActive;
        public int InactiveCount => pool.CountInactive;
        public int TotalCount => pool.CountAll;

        protected void Initialize(bool collectionCheck = true) =>
            pool = new ObjectPool<T>(OnCreatePoolItem, OnGetPoolItem, OnReleasePoolItem, OnDestroyPoolItem,
                collectionCheck, defaultSize, maxSize);

        protected virtual T OnCreatePoolItem() => Instantiate(prefab, transform);
        protected virtual void OnGetPoolItem(T obj) => obj.gameObject.SetActive(true);
        protected virtual void OnReleasePoolItem(T obj) => obj.gameObject.SetActive(false);
        protected virtual void OnDestroyPoolItem(T obj) => Destroy(obj.gameObject);

        public T Get() => pool.Get();
        public void Release(T obj) => pool.Release(obj);
        public void Clear() => pool.Clear();
    }

    public class TransformPool:ComponentPool<Transform>
    {
        public void SetPrefab(Transform prefab)
        {
            this.prefab = prefab;
        }
    }
    /// <summary>
    /// 带默认的对象池对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class MonoBehaviourPool<T> where T : MonoBehaviour
    {
        ObjectPool<T> _pool;

        protected virtual T OnCreatePoolItem()
        {
            var instance = new GameObject();
            return instance.AddComponent<T>();
        }

        public MonoBehaviourPool()
        {
            _pool = new ObjectPool<T>(
                OnCreatePoolItem, OnGetPoolItem, OnReleasePoolItem, OnDestroyPoolItem);
        }

        protected virtual void OnGetPoolItem(T obj) => obj.enabled = true;
        protected virtual void OnReleasePoolItem(T obj) => obj.enabled = false;
        protected virtual void OnDestroyPoolItem(T obj) => UnityEngine.Object.Destroy(obj.gameObject);
        public T Get() => _pool.Get();
        public void Release(T obj) => _pool.Release(obj);
        public void Clear() => _pool.Clear();
    }

    public class RendererPool<T> where T : Renderer
    {
        T _perfab;
        ObjectPool<T> _pool;

        protected virtual T OnCreatePoolItem()
        {
            return UnityEngine.Object.Instantiate(_perfab);
        }

        public RendererPool(T perfab)
        {
            _perfab = perfab;
            _pool = new ObjectPool<T>(
                OnCreatePoolItem, OnGetPoolItem, OnReleasePoolItem, OnDestroyPoolItem);
        }

        protected virtual void OnGetPoolItem(T obj) => obj.enabled = true;
        protected virtual void OnReleasePoolItem(T obj) => obj.enabled = false;
        protected virtual void OnDestroyPoolItem(T obj) => UnityEngine.Object.Destroy(obj.gameObject);
        public T Get() => _pool.Get();
        public void Release(T obj) => _pool.Release(obj);
        public void Clear() => _pool.Clear();
    }
}